package cn.lingyangwl.agile.pay.pay.process;

import cn.lingyangwl.agile.pay.common.constants.PayCacheKey;
import cn.lingyangwl.agile.pay.common.constants.PayNodeEnum;
import cn.lingyangwl.agile.pay.common.service.PayNodeService;
import cn.lingyangwl.agile.pay.common.service.RefundOrderService;
import cn.lingyangwl.agile.pay.pay.channel.AbstractRefundService;
import cn.lingyangwl.agile.pay.pay.channel.IRefundService;
import cn.lingyangwl.agile.pay.pay.model.bo.MchAppConfigContext;
import cn.lingyangwl.agile.pay.pay.model.rqrs.ChannelRetMsgExt;
import cn.lingyangwl.agile.pay.pay.service.ConfigContextQueryService;
import cn.lingyangwl.agile.pay.pay.service.PayMchNotifyService;
import cn.lingyangwl.framework.lock.manager.ILockManager;
import cn.lingyangwl.framework.lock.model.ILock;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import cn.lingyangwl.agile.pay.model.entity.PayNode;
import cn.lingyangwl.agile.pay.model.entity.RefundOrder;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 退款处理通用逻辑
 */
@Service
@Slf4j
public class ChannelRefundOrderProcess {

    @Resource
    private RefundOrderService refundOrderService;
    @Resource
    private PayMchNotifyService payMchNotifyService;
    @Resource
    private ConfigContextQueryService configContextQueryService;
    @Resource
    private ILockManager lockManager;
    @Resource
    private PayNodeService payNodeService;

    /**
     * 根据通道返回的状态，处理退款订单业务
     */
    public boolean handleRefundOrder4Channel(ChannelRetMsgExt channelRetMsgExt, RefundOrder refundOrder) {
        boolean updateOrderSuccess = true; // 默认更新成功
        String refundOrderId = refundOrder.getRefundOrderId();

        // 明确退款成功
        if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.CONFIRM_SUCCESS) {
            updateOrderSuccess = refundOrderService.updateIng2Success(refundOrderId, channelRetMsgExt.getChannelOrderId());
            if (updateOrderSuccess) {
                // 通知商户系统
                if (StringUtils.isNotEmpty(refundOrder.getNotifyUrl())) {
                    payMchNotifyService.refundOrderNotify(refundOrderService.getById(refundOrderId));
                }
            }
            // 确认失败
        } else if (channelRetMsgExt.getChannelState() == ChannelRetMsgExt.ChannelState.CONFIRM_FAIL) {
            // 更新为失败状态
            updateOrderSuccess = refundOrderService.updateIng2Fail(refundOrderId, channelRetMsgExt.getChannelOrderId(), channelRetMsgExt.getChannelErrCode(), channelRetMsgExt.getChannelErrMsg());
            // 通知商户系统
            if (StringUtils.isNotEmpty(refundOrder.getNotifyUrl())) {
                payMchNotifyService.refundOrderNotify(refundOrderService.getById(refundOrderId));
            }
        }
        return updateOrderSuccess;
    }


    /**
     * 处理退款订单
     */
    public void processRefundOrder(RefundOrder refundOrder) {
        PayNode payNode = PayNode.builder().titleCode(PayNodeEnum.REFUND_OK.getCode()).build();
        ILock lock = lockManager.getLock(PayCacheKey.PAY_GLOBAL_LOCK.formatKey(refundOrder.getPayOrderNo()));
        boolean tryLock = lock.tryLock(5, TimeUnit.SECONDS);
        if (!tryLock) {
            throw new BizException("该订单锁抢占超时, refundOrderId: {}, payOrderNo: {}",
                    refundOrder.getRefundOrderId(), refundOrder.getPayOrderNo());
        }
        try {
            if (refundOrder.getStatus().equalsIgnoreCase(RefundOrder.STATE_SUCCESS)) {
                log.info("订单已经退款, 取消本次订单退款, refundOrderId: {}", refundOrder.getRefundOrderId());
                return;
            }

            String refundOrderId = refundOrder.getRefundOrderId();

            // 查询支付接口是否存在
            IRefundService queryService = AbstractRefundService.getService(refundOrder.getIfCode());

            // 支付通道接口实现不存在
            if (queryService == null) {
                log.error("退款补单：{} interface not exists!", refundOrder.getIfCode());
                return;
            }

            // 查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(refundOrder.getMchNo(), refundOrder.getAppId());

            ChannelRetMsgExt channelRetMsgExt = queryService.query(refundOrder, mchAppConfigContext);
            if (channelRetMsgExt == null) {
                log.error("退款补单：channelRetMsg is null");
                return;
            }
            payNode.setPayOrderNo(refundOrder.getPayOrderNo());

            log.info("退款补单：[{}]查询结果为：{}", refundOrderId, JSON.toJSONString(channelRetMsgExt));
            // 根据渠道返回结果，处理退款订单
            boolean ret = this.handleRefundOrder4Channel(channelRetMsgExt, refundOrder);
            if (!ret) {
                payNode.setTitleCode(PayNodeEnum.REFUND_FAIL.getCode());
            }
        } catch (Exception e) {  // 继续下一次迭代查询
            payNode.setTitleCode(PayNodeEnum.REFUND_FAIL.getCode());
            log.error("退款补单：error refundOrderId = {}", refundOrder.getRefundOrderId(), e);
        } finally {
            lock.unlock();
            payNodeService.savePayNode(payNode);
        }
    }
}
